﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace ggprot
{
    public class PacketFactory
    {
        private Queue<GGHeader> packetQueue;
        private NetworkStream str;
        private bool isSending;

        public GGHeader GetPacket()
        {
            GGHeader header = new GGHeader();
            header.Read(str);

            switch (header.Type)
            {
                case (int)Packets.Welcome:
                    GGWelcome welcome = new GGWelcome(header);
                    welcome.Read(str);
                    return welcome;
                case (int)Packets.LoginFailed:
                    GGLoginFailed failed = new GGLoginFailed(header);
                    failed.Read(str);
                    return failed;
                case (int)Packets.LoginOk:
                    GGLoginOK succeed = new GGLoginOK(header);
                    succeed.Read(str);
                    return succeed;
                case (int)Packets.NotifyReply:
                    GGNotifyReply reply = new GGNotifyReply(header);
                    reply.Read(str);
                    return reply;
                case (int)Packets.Status:
                    GGNotifyReply status = new GGNotifyReply(header);
                    status.Read(str);
                    return status;
                case (int)Packets.UserData:
                    GGUserData udata = new GGUserData(header);
                    udata.Read(str);
                    return udata;
                case (int)Packets.XmlAction:
                    GGXmlAction xmla = new GGXmlAction(header);
                    xmla.Read(str);
                    return xmla;
                case (int)Packets.MsgAck:
                    GGMsgAck ack = new GGMsgAck(header);
                    ack.Read(str);
                    return ack;
                case (int)Packets.RecvMsg:
                    GGRecvMsg recv = new GGRecvMsg(header);
                    recv.Read(str);
                    return recv;
                case (int)Packets.OwnMsg: goto case (int)Packets.RecvMsg;
                case (int)Packets.TypeNotif:
                    GGTypingNotify notif = new GGTypingNotify(header);
                    notif.Read(str);
                    return notif;
                case (int)Packets.MultiLoginInfo:
                    GGMultiloginInfo multilogin = new GGMultiloginInfo(header);
                    multilogin.Read(str);
                    return multilogin;
                default: return header;
            }
        }

        public PacketFactory(NetworkStream str)
        {
            packetQueue = new Queue<GGHeader>();
            this.str = str;
            isSending = false;
        }

        public void SendPacket(GGHeader packet)
        {
            packetQueue.Enqueue(packet);
            Send();
        }

        private void Send()
        {
            if (isSending)
                return;

            isSending = true;
            packetQueue.Dequeue().Write(str);
            isSending = false;

            if (packetQueue.Count > 0)
                Send();
        }
    }
}
